/****************************************************************
Compile: gcc -O3 -o majority majority.c
Usage: ./majority input-1

This program is used to calculate the trajectory for a given network
under the majority rules. Moreover, it would check whether two additional
rules is satisfied or not in each timestep

Format of the inputfile:
first row            : N (number of the nodes)
second row           : s(1) s(2) ... s(n) (initial state)
the following N rows : network topology (for example, (i,j)=g means that 
                       node j can activate node i
****************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void print_help ()
{
	printf ("Usage         : ./majority inputfile\n");
	printf ("                (./majority input-1)\n\n");
	printf ("This program is used to calculate the trajectory for a given network\n");
	printf ("under the majority rules. Moreover, it would check whether additional\n");
	printf ("rules is satisfied or not in each timestep.\n\n");
}

int main (int argc, char *argv[])
{
	int i, j, N;
	FILE *fp;
	char buf[256];

	if (argc == 1)
	{
		print_help ();
		exit (0);
	}

	fp = fopen (argv[1], "r");
	fgets (buf, 256, fp);
	sscanf (buf, "%d", &N);

	int state1[N], state2[N], state3[N], network[N][N], flag;

	for (i = 0; i < N; i++)
	{
		fscanf (fp, "%d", &state1[i]);
	}
	fgets (buf, 256, fp);

	for (i = 0; i < N; i++)
	{
		fgets (buf, 256, fp);
		for (j = 0; j < N; j++)
		{
			if (buf[2 * j] == 'g')
			{
				if (i != j)
					network[i][j] = 2;
				else
					network[i][j] = 1;
			}
			else if (buf[2 * j] == 'r')
			{
				if (i != j)
					network[i][j] = -2;
				else
					network[i][j] = -1;
			}
			else
				network[i][j] = 0;
		}
	}

	fclose (fp);

	memcpy (state2, state1, sizeof (int) * N);

	while (1)
	{
		for (i = 0; i < N; i++)
		{
			flag = network[i][i];
			for (j = 0; j < N; j++)
			{
				flag += state2[j] * network[i][j];
			}

			if (flag > 0)
				state3[i] = 1;
			else if (flag < 0)
				state3[i] = 0;
			else
				state3[i] = state2[i];
		}

		for (i = 0; i < N; i++)
		{
			printf ("%d ", state2[i]);
		}
		printf ("\n");

		flag = 0;
		for (i = 0; i < N; i++)
		{
			if (state2[i] != state3[i])
			{
				flag = 1;
				break;
			}
		}
		if (flag == 0)
			break;

		/* check reliable transfer */
		for (i = 0; i < N; i++)
		{
			if (state2[i] == state3[i])
				continue;

			flag = network[i][i];
			for (j = 0; j < N; j++)
			{
				if (i == j)
					continue;

				flag += state2[j] * state3[j] * network[i][j];
			}
			for (j = 0; j < N; j++)
			{
				if (i == j)
					continue;

				if (state2[j] == state3[j])
					continue;

				if (state2[i] == 1)
				{
					if (network[i][j] > 0)
						flag += network[i][j];
				}
				else
				{
					if (network[i][j] < 0)
						flag += network[i][j];
				}
			}
			if (flag >= 0 && state3[i] == 0)
				printf ("Reliable Rules Failed on Node %d.\n", i);
			else if (flag <= 0 && state3[i] == 1)
				printf ("Reliable Rules Failed on Node %d.\n", i);
		}

		/* check middle state to middle state */
		for (i = 0; i < N; i++)
		{
			if (state2[i] != state3[i])
				continue;

			flag = network[i][i];
			for (j = 0; j < N; j++)
			{
				if (i == j)
					continue;

				flag += state1[j] * state2[j] * network[i][j];
			}
			for (j = 0; j < N; j++)
			{
				if (i == j)
					continue;

				if (state1[j] == state2[j])
					continue;

				if (state2[i] == 1)
				{
					if (network[i][j] < 0)
						flag += network[i][j];
				}
				else
				{
					if (network[i][j] > 0)
						flag += network[i][j];
				}
			}
			if (flag > 0 && state2[i] == 0)
				printf ("MtoM Rules Failed on Node %d.\n", i);
			else if (flag < 0 && state2[i] == 1)
				printf ("MtoM Rules Failed on Node %d.\n", i);
		}

		memcpy (state1, state2, sizeof (int) * N);
		memcpy (state2, state3, sizeof (int) * N);
	}
}
